/*
 * sparc header file
 * $Id: sparc.h,v 1.10 2012/07/21 00:05:04 curt Exp $
 */
typedef struct itype_s itype;

#define REG_G0  0
#define REG_O0  8
#define REG_O6  14
#define REG_O7  15
#define REG_L0  16
#define REG_I0  24
#define REG_I7  31

/*
 * these predefined expressions are used in many places, so we define them
 * once.
 */
expr *g0_expr;      /* hardwired to zero */
expr *ret_expr;
expr *sp_expr;

expr *c10_expr;     /* shift counts */
expr *c32_expr;
expr *c42_expr;

expr *m10_expr;     /* masks */
expr *m22_expr;

expr *reg_expr[32];

/*
 * indexes into attribute array of inst
 */
#define A_RD		0
#define A_RS1		1
#define A_RS2		2
#define A_DISP		3
#define A_A         4
#define A_P         5
#define A_CC		6
#define A_SREG		7
#define A_MEMBAR	8
#define A_ASI		9
#define A_COND      10
#define A_CTYPE     11

/*
 * instruction patterns - one for every single distinct instruction decoding
 * nothing will match the pattern in index 0.
 */
struct itype_s {
    char *name;

    uint32 opmask;		/* mask to use for match */
    uint32 opvalue;		/* must equal this under mask */

    uint32 format;		/* instruction prints with format */
    uint32 syndrome;	/* how to crack */
    operator_e op;		/* ALU operation */
};

itype instr[];

/*
 * syndrome flags that indicate that a field needs to be extracted
 * and saved into the attr array in the inst
 */
#define S_RD        0x00000001		/* destination register */
#define S_RS1       0x00000002		/* source 1 */
#define S_RS2       0x00000004		/* source 2 */
#define S_DISP      0x00000008		/* constant/displacement */

#define S_A         0x00000010		/* delay slot annul */
#define S_P         0x00000020		/* branch predict */
#define S_CC        0x00000040		/* which condition code */
#define S_SREG      0x00000080		/* special register id */

#define S_MEMBAR    0x00000100		/* membar options */
#define S_ASI       0x00000200		/* address space id */
#define S_COND      0x00000400      /* branch/move condition */
#define S_CTYPE     0x00000800      /* branch/move condition type */

/* location and widths of constants */
#define S_DISPMASK  0x00007000

#define SD_DISP5    (0 << 12)     	/* 32 bit shift amount */
#define SD_DISP6    (1 << 12)     	/* 64 bit shift amount */
#define SD_DISP10   (2 << 12)
#define SD_DISP13   (3 << 12)
#define SD_DISP16   (4 << 12)       /* bpr */
#define SD_DISP19   (5 << 12)       /* bpcc, fbpfcc */
#define SD_DISP22   (6 << 12)       /* sethi, bicc, fbfcc */
#define SD_DISP30   (7 << 12)       /* call */

#define S_PCREL     0x00008000		/* program counter to be added */

/* location and widths of condition encoding */
#define S_CONDMASK  0x00070000
#define SC_BCC      (0 << 16)
#define SC_BPR      (1 << 16)
#define SC_MOVR     (2 << 16)
#define SC_MOVCC    (3 << 16)
#define SC_FMOVCC   (4 << 16)
#define SC_FMOVR    (5 << 16)
#define SC_FBFCC    (6 << 16)
#define SC_FBPFCC   (7 << 16)

#define S_SETCC     0x00080000      /* sets CC */

#define S_ASIR      0x00100000		/* dereference use ASI register */
#define S_U32_Z     0x00200000      /* instr clears upper longword */

/* special handling */
#define S_SAVE      0x01000000
#define S_RESTORE   0x02000000
#define S_CALL      0x04000000
#define S_IF        0x08000000
#define S_LOAD      0x10000000
#define S_STORE     0x20000000
#define	S_CWP	    0x40000000		/* instr changes windows */
#define S_JUMP      0x80000000

#define S_UNUSED    0x00c00000

char *regname[];

/*
 * these are sparc relocation types handed to us by bfd
 * we map these double indirect through this table to macro names
 * sparc relocation types
 *  RELOC_DISP30    0x7         address32 >> 2 & 0x3fffffff
 *  RELOC_HI22      0x9         address32 >> 10 & 0x3fffff
 *  RELOC_LL10      0xc         address & 0x3ff
 *  RELOC_ALL       0x20        address32 & 0xffffffff
 *  RELOC_HH22      0x22        address64 >> 42 & 0x3fffff
 *  RELOC_HM10      0x23        address64 >> 32 & 0x3ff
 *  RELOC_LM22      0x24        address64 >> 10 & 0x3fffff
 *
 * we make sure this table is a power of two in size, so we can
 * mask our index and prevent segv's
 *
 * XXX -
 * it is utterly lame that bfd doesn't define these symbolically,
 * since it is part of the interface. I'll do it here.  if these
 * numbers change, then we lose and will have to fix it.
 */
/* they are, however defined in #include <sys/elf_SPARC.h> */

#define RELOC_DISP30    0x7 	/* R_SPARC_WDISP30 */
#define RELOC_HI22  	0x9 	/* R_SPARC_HI22 */
#define RELOC_LL10      0xc 	/* R_SPARC_LO10 */
#define RELOC_ALL       0x20	/* R_SPARC_64 */
#define RELOC_HH22      0x22	/* R_SPARC_HH22 */
#define RELOC_HM10      0x23	/* R_SPARC_HM10 */
#define RELOC_LM22      0x24	/* R_SPARC_LM22 */
